﻿using System;
using Sirenix.OdinInspector;
using UnityEngine;

namespace IQIGame.Onigao.GamePlay
{
    public class CameraCurveConfig : ScriptableObject
    {
        public const int targetMaxNum = 6;

        public Quaternion rootRotation;
        public AnimationCurveArr pos = new AnimationCurveArr(3);
        public AnimationCurveArr rot = new AnimationCurveArr(4);
        public AnimationCurve fov;
        public float duration;
        public AnimationCurveArr[] targetPos = new AnimationCurveArr[targetMaxNum];
        public AnimationCurveArr[] targetRot = new AnimationCurveArr[targetMaxNum];
        public CameraCurveConfig Clone()
        {
            var clone = ScriptableObject.CreateInstance<CameraCurveConfig>();
            clone.rootRotation = this.rootRotation;
            clone.pos = this.pos;
            clone.rot = this.rot;
            clone.fov = this.fov;
            clone.duration = this.duration;
            clone.targetPos = this.targetPos;
            clone.targetRot = this.targetRot;
            return clone;
        }

        public static bool TryGetVector3(AnimationCurveArr arr, float time, out Vector3 value)
        {
            var rCurve = arr.value;
            if (rCurve is { Length: >= 3 })
            {
                var x = GetCurveValue(rCurve[0],time);
                var y = GetCurveValue(rCurve[1],time);
                var z = GetCurveValue(rCurve[2],time);
                value = new Vector3(x, y, z);
                return value != Vector3.zero;
            }
            value = Vector3.zero;
            return false;
        }
        
        public static bool TryGetQuaternion(AnimationCurveArr arr, float time, out Quaternion value)
        {
            var rCurve = arr.value;
            if (rCurve is { Length: >= 4 })
            {
                var x = GetCurveValue(rCurve[0],time);
                var y = GetCurveValue(rCurve[1],time);
                var z = GetCurveValue(rCurve[2],time);
                var w = GetCurveValue(rCurve[3],time);
                value = new Quaternion(x, y, z, w);
                return x != 0 || y != 0 || z != 0 || w != 0;
            }
            value = Quaternion.identity;
            return false;
        }

        public static float GetCurveValue(AnimationCurve curve, float time)
        {
            var fMaxTime = curve.keys.Length > 0 ? curve.keys[^1].time : 0;
            if (fMaxTime < time)
            {
                time = fMaxTime;
            }
            return curve.Evaluate(time);
        }

        [Serializable]
        public class AnimationCurveArr
        {
            public AnimationCurve[] value;

            public AnimationCurveArr(int num)
            {
                this.value = new AnimationCurve[num];
            }
        }
    }
}